package com.tuo51.foudation.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.matt.commons.exception.BusinessException;
import com.matt.commons.model.ErrorCode;
import com.tuo51.foudation.model.StatusResponse;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.validation.constraints.NotNull;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;

import static com.matt.commons.model.ErrorCode.JSON_STR_ERROR;

/**
 * *******************************
 * Created by Ron.
 * form com.tuo51
 * on 2017/7/11
 * *******************************
 */
public class ModelUtil {

    public static ObjectMapper objectMapper = new ObjectMapper();

    public static Integer getMonth(Long days) {
        return (int) (days / 30L + 1L);
    }

    public static Integer getDay(Long days) {
        return (int) (days % 30L + 1L);
    }


    public static String getCleanUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }


    public static String getSafeStr(Object obj) {
        return obj == null ? "" : obj.toString();
    }

    public static Integer getNullInteger(Object obj) {
        return obj == null ? null : Integer.valueOf(obj.toString());
    }

    public static Integer getDefaultInteger(Object obj) {
        return obj == null ? 0 : Integer.valueOf(obj.toString());
    }


    public static String numToStr(Integer num) {
        if (num < 10)
            return "00" + num;
        if (num < 100)
            return "0" + num;
        else
            return "" + num;
    }

    public static String numToStrLenth2(Integer num) {
        if (num < 10)
            return "0" + num;
        else
            return "" + num;
    }


    public static String getAreaCityCode(String areaName) {
        if (areaName.startsWith("成都"))
            return "51";
        if (areaName.startsWith("上海"))
            return "31";
        if (areaName.startsWith("北京"))
            return "11";
        return getRandomNumber(2);
    }
    
    public static String getRandomNumber(int length){
		String val = "";
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			val += String.valueOf(random.nextInt(10));
		}
		return val;
    }
    public static final String getRandomSerial(Integer length) {
        return RandomStringUtils.random(length, 48, 58, false, true);
    }

    public static final Integer matchLatelyMonth(Integer month) {
        if (month < 0)
            return 0;
        if (month < 7)
            return 7;
        if (month > 48)
            return 48;
        return month;
    }


    public static final Integer compute(Integer src, String formula){
        try {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine se = manager.getEngineByName("js");
            String str = formula.replace("X", String.valueOf(src));
            Double result =(Double) se.eval(str);
            return (int) result.doubleValue();
        }catch (ScriptException e){
            e.printStackTrace();
        }
        return 0;
    }

    public static void main(String []args){
        //int result =11 ;
       // String formula ="100+15*(X-8.5)/1.7";

       // int score = compute(result,formula);
       // System.out.println(score);
        System.out.println(getRandomNumber(2));
    }

    @SuppressWarnings("rawtypes")
    public static final void copyNotNullProperties(@NotNull Object dest,
                                                   @NotNull Object orig) throws IllegalAccessException,
            InvocationTargetException {
        BeanUtilsBean beanUtils = BeanUtilsBean.getInstance();
        // Copy the properties, converting as necessary
        if(orig instanceof DynaBean){
            DynaProperty[] origDescriptors = ((DynaBean) orig).getDynaClass()
                    .getDynaProperties();
            for(int i = 0; i < origDescriptors.length; i++){
                String name = origDescriptors[i].getName();

                // Need to check isReadable() for WrapDynaBean
                // (see Jira issue# BEANUTILS-61)
                if(beanUtils.getPropertyUtils().isReadable(orig, name)
                        && beanUtils.getPropertyUtils().isWriteable(dest, name)){
                    Object value = ((DynaBean) orig).get(name);
                    beanUtils.copyProperty(dest, name, value);
                }
            }
        }else if(orig instanceof Map){
            Iterator entries = ((Map) orig).entrySet().iterator();
            while(entries.hasNext()){
                Map.Entry entry = (Map.Entry) entries.next();
                String name = (String) entry.getKey();
                if(beanUtils.getPropertyUtils().isWriteable(dest, name)){
                    beanUtils.copyProperty(dest, name, entry.getValue());
                }
            }
        }else /* if (orig is a standard JavaBean) */{
            PropertyDescriptor[] origDescriptors = beanUtils.getPropertyUtils()
                    .getPropertyDescriptors(orig);
            for(int i = 0; i < origDescriptors.length; i++){
                String name = origDescriptors[i].getName();
                if("class".equals(name)){
                    continue; // No point in trying to set an object's class
                }
                if(beanUtils.getPropertyUtils().isReadable(orig, name)
                        && beanUtils.getPropertyUtils().isWriteable(dest, name)){
                    try{
                        Object value = beanUtils.getPropertyUtils()
                                .getSimpleProperty(orig, name);
                        if(null == value)
                            continue;
                        Class<? extends Object> valueType = value.getClass();
                        if(value instanceof Collection || value instanceof Map){
                            Method method = ReflectionUtils.findMethod(
                                    valueType, "size");
                            int size = (int) method.invoke(value);
                            if(0 == size)
                                continue;
                        }
                        if(valueType.isArray())
                            if(0 == Array.getLength(value))
                                continue;
                        beanUtils.copyProperty(dest, name, value);
                    }catch(NoSuchMethodException e){
                        // Should not happen
                    }
                }
            }
        }
    }
    

    @SuppressWarnings("rawtypes")
    public static final void copyNotNullPropertiesExcludeId(@NotNull Object dest,
                                                            @NotNull Object orig) throws IllegalAccessException,
            InvocationTargetException {
        BeanUtilsBean beanUtils = BeanUtilsBean.getInstance();
        // Copy the properties, converting as necessary
        if(orig instanceof DynaBean){
            DynaProperty[] origDescriptors = ((DynaBean) orig).getDynaClass()
                    .getDynaProperties();
            for(int i = 0; i < origDescriptors.length; i++){
                String name = origDescriptors[i].getName();
                if (name.equals("id"))
                    continue;
                // Need to check isReadable() for WrapDynaBean
                // (see Jira issue# BEANUTILS-61)
                if(beanUtils.getPropertyUtils().isReadable(orig, name)
                        && beanUtils.getPropertyUtils().isWriteable(dest, name)){
                    Object value = ((DynaBean) orig).get(name);
                    beanUtils.copyProperty(dest, name, value);
                }
            }
        }else if(orig instanceof Map){
            Iterator entries = ((Map) orig).entrySet().iterator();
            while(entries.hasNext()){
                Map.Entry entry = (Map.Entry) entries.next();
                String name = (String) entry.getKey();
                if(beanUtils.getPropertyUtils().isWriteable(dest, name)){
                    beanUtils.copyProperty(dest, name, entry.getValue());
                }
            }
        }else /* if (orig is a standard JavaBean) */{
            PropertyDescriptor[] origDescriptors = beanUtils.getPropertyUtils()
                    .getPropertyDescriptors(orig);
            for(int i = 0; i < origDescriptors.length; i++){
                String name = origDescriptors[i].getName();
                if (name.equals("id"))
                    continue;
                if("class".equals(name)){
                    continue; // No point in trying to set an object's class
                }
                if(beanUtils.getPropertyUtils().isReadable(orig, name)
                        && beanUtils.getPropertyUtils().isWriteable(dest, name)){
                    try{
                        Object value = beanUtils.getPropertyUtils()
                                .getSimpleProperty(orig, name);
                        if(null == value)
                            continue;
                        Class<? extends Object> valueType = value.getClass();
                        if(value instanceof Collection || value instanceof Map){
                            Method method = ReflectionUtils.findMethod(
                                    valueType, "size");
                            int size = (int) method.invoke(value);
                            if(0 == size)
                                continue;
                        }
                        if(valueType.isArray())
                            if(0 == Array.getLength(value))
                                continue;
                        beanUtils.copyProperty(dest, name, value);
                    }catch(NoSuchMethodException e){
                        // Should not happen
                    }
                }
            }
        }
    }


    public static Map mapOf(List keys, List values){
        Map map =new HashMap();
        for (int i = 0 ; i<keys.size(); i++){
            if (Objects.isNull(keys.get(i)))
                throw new BusinessException(ErrorCode.UNDEFINED, "keys不能为空");
            map.put(keys.get(i), values.get(i));
        }
        return map;
    }

    public static Map mapOf(Object key1, Object value1){
        Map map =new HashMap();
        map.put(key1, value1);
        return map;
    }

    public static Map mapOf(Object key1, Object value1, Object key2, Object value2){
        Map map =new HashMap();
        map.put(key1, value1);
        map.put(key2, value2);
        return map;
    }

    public static String joinQuota(List<String> resource){
        List<String> b =new ArrayList<String>();
        for (String string : resource) {
            b.add("'"+string+"'");
        }
        String list = Pattern.compile("\\b([\\w\\W])\\b").matcher(b.toString().substring(1,b.toString().length()-1)).replaceAll("'$1'");
        return list;
    }



    public static String getSuffixUrl(String videoUrl) {
        if (StringUtils.isBlank(videoUrl))
            return null;
        String str[] = videoUrl.split("/");
        return str[str.length - 1];
    }

    public static StatusResponse getResponse(String src, String errorMsg) {
        try {
            StatusResponse statusResponse = objectMapper.readValue(src, StatusResponse.class);
            if (statusResponse.getCode().equals(ErrorCode.UNDEFINED))
                throw new BusinessException(statusResponse.getCode(), errorMsg);
            if (!statusResponse.getCode().equals(ErrorCode.SUCCESSFUL))
                throw new BusinessException(statusResponse.getCode(), statusResponse.getMessage());
            return statusResponse;
        } catch (IOException e) {
            throw new BusinessException(JSON_STR_ERROR, errorMsg);
        }
    }

    public static String toJson(Object o){
        try {
            return objectMapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.UNDEFINED, "json转换出错");
        }
    }
}
